/*
 * Copyright (c) 2025 Industrial Software Feature Database
 */
package com.comac.ins.isfd.service.impl;


import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.comac.ins.common.core.constant.CommonConstant;
import com.comac.ins.common.core.exception.base.BaseException;
import com.comac.ins.common.core.utils.MapstructUtils;
import com.comac.ins.common.core.utils.StringUtils;
import com.comac.ins.common.mybatis.core.page.PageQuery;
import com.comac.ins.common.mybatis.core.page.TableDataInfo;
import com.comac.ins.isfd.constant.enums.ActionTypeEnum;
import com.comac.ins.isfd.constant.enums.IsfdModelManagementDownLoadTypeEnum;
import com.comac.ins.isfd.domain.IsfdModelManagementCalculateFile;
import com.comac.ins.isfd.domain.bo.*;
import com.comac.ins.isfd.domain.vo.*;
import com.comac.ins.isfd.mapper.IsfdModelManagementCalculateFileMapper;
import com.comac.ins.isfd.service.*;
import com.comac.ins.isfd.util.FileUtils;
import com.comac.ins.system.service.ISysDictDataService;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.zip.ZipOutputStream;

import static com.comac.ins.common.mybatis.core.mapper.BaseMapperPlus.log;

/**
 * 计算文件记录Service业务层处理
 *
 * @author Lion Li
 * @date 2024-08-19
 */
@RequiredArgsConstructor
@Service
public class IsfdModelManagementCalculateFileServiceImpl implements IIsfdModelManagementCalculateFileService {

    @Autowired
    private IsfdModelManagementCalculateFileMapper baseMapper;

    @Autowired
    private IIsfdModelManagementPartService iIsfdModelManagementPartService;

    @Autowired
    private IIsfdModelManagementNecessaryItemsService iIsfdModelManagementNecessaryItemsService;

    @Autowired
    private IIsfdModelManagementCalculateRefNecessaryItemsService iIsfdModelManagementCalculateRefNecessaryItemsService;

    @Autowired
    private IIsfdModelManagementBoundaryService iIsfdModelManagementBoundaryService;

    @Autowired
    private IIsfdModelManagementCalculateRefBoundaryService iIsfdModelManagementCalculateRefBoundaryService;

    @Autowired
    private IIsfdModelManagementLoadService iIsfdModelManagementLoadService;

    @Autowired
    private IIsfdModelManagementCalculateRefLoadService iIsfdModelManagementCalculateRefLoadService;

    @Autowired
    private IIsfdModelManagementNonstandardocsService iIsfdModelManagementNonstandardocsService;

    @Autowired
    private IIsfdModelManagementCalculateRefNonstandardocsService iIsfdModelManagementCalculateRefNonstandardocsService;

    @Autowired
    @Lazy
    private IsfdModelManagementTaskServiceImpl isfdModelManagementTaskService;

    @Autowired
    private ISysDictDataService iSysDictDataService;


    @Override
    public IsfdModelManagementCalculateFileDetailVo queryDetailVoById(Long id) {
        IsfdModelManagementCalculateFileDetailVo result = new IsfdModelManagementCalculateFileDetailVo();
        IsfdModelManagementCalculateFileVo isfdModelManagementCalculateFileVo = baseMapper.selectVoById(id);
        if (isfdModelManagementCalculateFileVo == null) {
            throw new BaseException("计算文件记录详情信息不存在。");
        }
        // 计算文件记录基本信息
        BeanUtils.copyProperties(isfdModelManagementCalculateFileVo, result);

        // 已选择的零组件
        String[] split = isfdModelManagementCalculateFileVo.getPartIds().split(",");
        List<IsfdModelManagementPartVo> partVoList = iIsfdModelManagementPartService.queryList(Arrays.stream(split).map(Long::valueOf).toList());
        result.setPartVoList(partVoList);
        // 必备件
        result.setNecessaryItemsVoList(iIsfdModelManagementNecessaryItemsService.queryListByCalculateId(id));
        // 边界条件
        result.setBoundaryVoList(iIsfdModelManagementBoundaryService.queryListByCalculateId(id));
        // 载荷文件
        result.setLoadVoList(iIsfdModelManagementLoadService.queryListByCalculateId(id));
        // 非标文件
        result.setNonstandardocsVoList(iIsfdModelManagementNonstandardocsService.queryListByCalculateId(id));
        return result;
    }

    @Override
    public IsfdModelManagementCalculateFileVo queryById(Long id) {
        return baseMapper.selectVoById(id);
    }

    /**
     * 分页查询计算文件记录列表
     *
     * @param bo        查询条件
     * @param pageQuery 分页参数
     * @return 计算文件记录分页列表
     */
    @Override
    public TableDataInfo<IsfdModelManagementCalculateFileVo> queryPageList(IsfdModelManagementCalculateFileBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<IsfdModelManagementCalculateFile> lqw = buildQueryWrapper(bo);
        Page<IsfdModelManagementCalculateFileVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    /**
     * 查询符合条件的计算文件记录列表
     *
     * @param bo 查询条件
     * @return 计算文件记录列表
     */
    @Override
    public List<IsfdModelManagementCalculateFileVo> queryList(IsfdModelManagementCalculateFileBo bo) {
        LambdaQueryWrapper<IsfdModelManagementCalculateFile> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<IsfdModelManagementCalculateFile> buildQueryWrapper(IsfdModelManagementCalculateFileBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<IsfdModelManagementCalculateFile> lqw = Wrappers.lambdaQuery();
        lqw.eq(bo.getTaskId() != null, IsfdModelManagementCalculateFile::getTaskId, bo.getTaskId());
        lqw.eq(bo.getPartIds() != null, IsfdModelManagementCalculateFile::getPartIds, bo.getPartIds());
        return lqw;
    }

    /**
     * 新增计算文件记录
     *
     * @param bo 计算文件记录
     * @return 是否新增成功
     */
    @Override
    @Transactional
    public Boolean insertByBo(IsfdModelManagementCalculateFileBo bo) {
        IsfdModelManagementCalculateFile add = MapstructUtils.convert(bo, IsfdModelManagementCalculateFile.class);
        baseMapper.insert(add);
        //存储NecessaryItems必备件关联表
        List<IsfdModelManagementCalculateRefNecessaryItemsBo> refNecessaryItemsBos = new ArrayList<>();
        bo.getNecessaryItemsIds().forEach(id -> {
            IsfdModelManagementCalculateRefNecessaryItemsBo refNecessaryItemsBo = new IsfdModelManagementCalculateRefNecessaryItemsBo();
            if (add != null) {
                refNecessaryItemsBo.setCalculateId(add.getId());
            }
            refNecessaryItemsBo.setNecessaryItemsId(id);
            refNecessaryItemsBos.add(refNecessaryItemsBo);
        });
        iIsfdModelManagementCalculateRefNecessaryItemsService.insertByBoList(refNecessaryItemsBos);
        //存储边界条件关联表
        List<IsfdModelManagementCalculateRefBoundaryBo> refBoundaryBos = new ArrayList<>();
        bo.getBoundaryIds().forEach(id -> {
            IsfdModelManagementCalculateRefBoundaryBo refBoundaryBo = new IsfdModelManagementCalculateRefBoundaryBo();
            if (add != null) {
                refBoundaryBo.setCalculateId(add.getId());
            }
            refBoundaryBo.setBoundaryId(id);
            refBoundaryBos.add(refBoundaryBo);
        });
        iIsfdModelManagementCalculateRefBoundaryService.insertByBoList(refBoundaryBos);
        //存储载荷关联表
        List<IsfdModelManagementCalculateRefLoadBo> refLoadBos = new ArrayList<>();
        bo.getLoadIds().forEach(id -> {
            IsfdModelManagementCalculateRefLoadBo refLoadBo = new IsfdModelManagementCalculateRefLoadBo();
            if (add != null) {
                refLoadBo.setCalculateId(add.getId());
            }
            refLoadBo.setLoadId(id);
            refLoadBos.add(refLoadBo);
        });
        iIsfdModelManagementCalculateRefLoadService.insertByBoList(refLoadBos);

        //存储非标文件关联关系
        List<IsfdModelManagementCalculateRefNonstandardocsBo> refNonstandardocsBos = new ArrayList<>();
        bo.getNonstandardocsIds().forEach(id -> {
            IsfdModelManagementCalculateRefNonstandardocsBo refNonstandardocsBo = new IsfdModelManagementCalculateRefNonstandardocsBo();
            if (add != null) {
                refNonstandardocsBo.setCalculateId(add.getId());
            }
            refNonstandardocsBo.setNonstandardocsId(id);
            refNonstandardocsBos.add(refNonstandardocsBo);
        });
        iIsfdModelManagementCalculateRefNonstandardocsService.insertbyBoList(refNonstandardocsBos);
        return Boolean.TRUE;
    }

    /**
     * 修改计算文件记录
     *
     * @param bo 计算文件记录 只能修改 必备件、边界条件和载荷文件
     * @return 是否修改成功
     */
    @Override
    @Transactional
    public Boolean updateByBo(IsfdModelManagementCalculateFileBo bo) {
        //删除必备件、边界条件和载荷文件关联数据
        iIsfdModelManagementCalculateRefNecessaryItemsService.deleteBycalculateId(bo.getId());
        iIsfdModelManagementCalculateRefBoundaryService.deleteBycalculateId(bo.getId());
        iIsfdModelManagementCalculateRefLoadService.deleteBycalculateId(bo.getId());
        iIsfdModelManagementCalculateRefNonstandardocsService.deleteByCalculateId(bo.getId());
        //增加新的关联数据
        //存储NecessaryItems必备件关联表
        List<IsfdModelManagementCalculateRefNecessaryItemsBo> refNecessaryItemsBos = new ArrayList<>();
        bo.getNecessaryItemsIds().forEach(id -> {
            IsfdModelManagementCalculateRefNecessaryItemsBo refNecessaryItemsBo = new IsfdModelManagementCalculateRefNecessaryItemsBo();
            refNecessaryItemsBo.setCalculateId(bo.getId());
            refNecessaryItemsBo.setNecessaryItemsId(id);
            refNecessaryItemsBos.add(refNecessaryItemsBo);
        });
        iIsfdModelManagementCalculateRefNecessaryItemsService.insertByBoList(refNecessaryItemsBos);
        //存储边界条件关联表
        List<IsfdModelManagementCalculateRefBoundaryBo> refBoundaryBos = new ArrayList<>();
        bo.getBoundaryIds().forEach(id -> {
            IsfdModelManagementCalculateRefBoundaryBo refBoundaryBo = new IsfdModelManagementCalculateRefBoundaryBo();
            refBoundaryBo.setCalculateId(bo.getId());
            refBoundaryBo.setBoundaryId(id);
            refBoundaryBos.add(refBoundaryBo);
        });
        iIsfdModelManagementCalculateRefBoundaryService.insertByBoList(refBoundaryBos);
        //存储载荷关联表
        List<IsfdModelManagementCalculateRefLoadBo> refLoadBos = new ArrayList<>();
        bo.getLoadIds().forEach(id -> {
            IsfdModelManagementCalculateRefLoadBo refLoadBo = new IsfdModelManagementCalculateRefLoadBo();
            refLoadBo.setCalculateId(bo.getId());
            refLoadBo.setLoadId(id);
            refLoadBos.add(refLoadBo);
        });
        iIsfdModelManagementCalculateRefLoadService.insertByBoList(refLoadBos);

        //存储非标文件关联关系
        List<IsfdModelManagementCalculateRefNonstandardocsBo> refNonstandardocsBos = new ArrayList<>();
        bo.getNonstandardocsIds().forEach(id -> {
            IsfdModelManagementCalculateRefNonstandardocsBo refNonstandardocsBo = new IsfdModelManagementCalculateRefNonstandardocsBo();
            refNonstandardocsBo.setCalculateId(bo.getId());
            refNonstandardocsBo.setNonstandardocsId(id);
            refNonstandardocsBos.add(refNonstandardocsBo);
        });
        iIsfdModelManagementCalculateRefNonstandardocsService.insertbyBoList(refNonstandardocsBos);

        return Boolean.TRUE;
    }

    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if (isValid) {
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteBatchIds(ids) > 0;
    }

    @Override
    public List<IsfdModelManagementCalculateFileVo> queryListByTaskId(Long taskId) {
        return baseMapper.selectVoList(new LambdaQueryWrapper<IsfdModelManagementCalculateFile>()
            .eq(IsfdModelManagementCalculateFile::getTaskId, taskId));
    }

    @Override
    public void partAndCalculateBdfDownload(Long id, HttpServletResponse response) {
        IsfdModelManagementCalculateFile isfdModelManagementCalculateFile = baseMapper.selectById(id);
        Long taskId = isfdModelManagementCalculateFile.getTaskId();

        //查询批次编号
        IsfdModelManagementTaskVo isfdModelManagementTaskVo = isfdModelManagementTaskService.queryById(taskId);
        String batchNumber = isfdModelManagementTaskVo.getBatchNumber();

        // 获取零件信息
        List<IsfdModelManagementPartVo> partVos = isfdModelManagementTaskService.getPartListByTaskId(taskId);
        if (CollectionUtils.isEmpty(partVos)) {
            throw new BaseException("任务未选择零件，不能下载！");
        }
        String partPrePath = iSysDictDataService.selectDictValueByTypeAndLabel(CommonConstant.SYS_COMMON_DICT_TYPE,
            CommonConstant.MODEL_MANAGEMENT_PART_DATA_PREFIX);
        if (StringUtils.isBlank(partPrePath)) {
            throw new BaseException("字典中没有找到文件存储地址的相关配置。");
        }
        // 获取zip包的跟目录
        String targetIndexPath = partVos.get(0).getIndexPath();
        String root = StringUtils.substringBefore(targetIndexPath, "/");
        List<String> partPaths = new ArrayList<>(partVos.stream().map(IsfdModelManagementPartVo::getIndexPath).toList());

        // 获取必备件信息
        IsfdModelManagementCalculateRefNecessaryItemsBo refNecessaryItemsBo = new IsfdModelManagementCalculateRefNecessaryItemsBo();
        refNecessaryItemsBo.setCalculateId(id);
        List<IsfdModelManagementCalculateRefNecessaryItemsVo> refNecessaryItemsVos = iIsfdModelManagementCalculateRefNecessaryItemsService.queryList(refNecessaryItemsBo);

        List<String> necessaryItemsIndexPaths = null;
        List<IsfdModelManagementTaskBdfDownLoadBo.NecessaryItems> necessaryItemsList = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(refNecessaryItemsVos)) {
            List<Long> necessaryIds = refNecessaryItemsVos.stream().map(IsfdModelManagementCalculateRefNecessaryItemsVo::getNecessaryItemsId).toList();
            List<IsfdModelManagementNecessaryItemsVo> isfdModelManagementNecessaryItemsVos = iIsfdModelManagementNecessaryItemsService.queryByBatchIds(necessaryIds);
            for (IsfdModelManagementNecessaryItemsVo isfdModelManagementNecessaryItemsVo : isfdModelManagementNecessaryItemsVos) {
                IsfdModelManagementTaskBdfDownLoadBo.NecessaryItems necessaryItems = new IsfdModelManagementTaskBdfDownLoadBo.NecessaryItems();
                // 获取必备件挂在 到具体的机型 、部段 还是 组件下的索引地址
                String indexPath = getNecessaryItemsIndexPaths(isfdModelManagementNecessaryItemsVo);
                necessaryItems.setIndexPath(indexPath);
                necessaryItems.setDiskPath(isfdModelManagementNecessaryItemsVo.getFileUrl());
                necessaryItemsList.add(necessaryItems);
            }
            necessaryItemsIndexPaths = necessaryItemsList.stream().map(IsfdModelManagementTaskBdfDownLoadBo.NecessaryItems::getIndexPath).toList();
        }

        // 获取边界条件信息
        IsfdModelManagementCalculateRefBoundaryBo refBoundaryBo = new IsfdModelManagementCalculateRefBoundaryBo();
        refBoundaryBo.setCalculateId(id);
        List<IsfdModelManagementCalculateRefBoundaryVo> refBoundaryVos = iIsfdModelManagementCalculateRefBoundaryService.queryList(refBoundaryBo);

        List<String> boundaryPaths = null;
        List<String> boundaryIndexPaths = null;
        if (CollectionUtils.isNotEmpty(refBoundaryVos)) {
            List<Long> boundaryIds = refBoundaryVos.stream().map(IsfdModelManagementCalculateRefBoundaryVo::getBoundaryId).toList();
            List<IsfdModelManagementBoundaryVo> isfdModelManagementBoundaryVos = iIsfdModelManagementBoundaryService.queryByBatchIds(boundaryIds);
            boundaryPaths = isfdModelManagementBoundaryVos.stream().map(IsfdModelManagementBoundaryVo::getFileUrl).toList();
            boundaryIndexPaths = isfdModelManagementBoundaryVos.stream().map(m -> root + "/" + m.getFileName()).toList();
        }

        // 获取载荷信息
        IsfdModelManagementCalculateRefLoadBo refLoadBo = new IsfdModelManagementCalculateRefLoadBo();
        refLoadBo.setCalculateId(id);
        List<IsfdModelManagementCalculateRefLoadVo> refLoadVos = iIsfdModelManagementCalculateRefLoadService.queryList(refLoadBo);
        List<String> loadPaths = null;
        List<String> loadIndexPaths = null;
        if (CollectionUtils.isNotEmpty(refLoadVos)) {
            List<Long> loadIds = refLoadVos.stream().map(IsfdModelManagementCalculateRefLoadVo::getLoadId).toList();
            List<IsfdModelManagementLoadVo> isfdModelManagementLoadVos = iIsfdModelManagementLoadService.queryByBatchIds(loadIds);
            loadPaths = isfdModelManagementLoadVos.stream().map(IsfdModelManagementLoadVo::getFileUrl).toList();
            loadIndexPaths = isfdModelManagementLoadVos.stream().map(m -> root + "/" + m.getFileName()).toList();
        }

        // 获取非标文件信息
        IsfdModelManagementCalculateRefNonstandardocsBo refNonstandardocsBo = new IsfdModelManagementCalculateRefNonstandardocsBo();
        refNonstandardocsBo.setCalculateId(id);
        List<IsfdModelManagementCalculateRefNonstandardocsVo> nonstandardocsVos = iIsfdModelManagementCalculateRefNonstandardocsService.queryList(refNonstandardocsBo);
        List<String> nonstandardocsPaths = null;
        List<String> nonstandardocsIndexPaths = null;
        if (CollectionUtils.isNotEmpty(nonstandardocsVos)) {
            List<Long> nonstandardIds = nonstandardocsVos.stream().map(IsfdModelManagementCalculateRefNonstandardocsVo::getNonstandardocsId).toList();
            List<IsfdModelManagementNonstandardocsVo> isfdModelManagementNonstandardocsVos = iIsfdModelManagementNonstandardocsService.queryByBatchIds(nonstandardIds);
            nonstandardocsPaths = isfdModelManagementNonstandardocsVos.stream().map(IsfdModelManagementNonstandardocsVo::getFileUrl).toList();
            nonstandardocsIndexPaths = isfdModelManagementNonstandardocsVos.stream().map(m -> root + "/" + m.getFileName()).toList();
        }

        // 1. 生成索引文件
        IsfdModelManagementTaskCreateIndexFileParamBo paramBo = new IsfdModelManagementTaskCreateIndexFileParamBo();
        paramBo.setCalculateId(id);
        paramBo.setPartIds(partVos.stream().map(IsfdModelManagementPartVo::getId).toList());
        paramBo.setActionTypeEnum(ActionTypeEnum.DOWNLOAD);
        paramBo.setIsfdModelManagementDownLoadTypeEnum(IsfdModelManagementDownLoadTypeEnum.CALCULATE);
        paramBo.setBoundaryIndexPaths(boundaryIndexPaths);
        paramBo.setLoadIndexPaths(loadIndexPaths);
        paramBo.setNonstandardIndexPaths(nonstandardocsIndexPaths);
        paramBo.setNecessaryItemsIndexPaths(necessaryItemsIndexPaths);
//        paramBo.setBatchNumber(batchNumber);

        IsfdModelManagementTaskCreateIndexFileResultBo resultBo = isfdModelManagementTaskService.createIndexFile(paramBo);
        List<File> indexFileList = resultBo.getIndexFileList();

        IsfdModelManagementTaskBdfDownLoadBo downLoadBo = new IsfdModelManagementTaskBdfDownLoadBo();
        downLoadBo.setPartPrePath(partPrePath);
        downLoadBo.setPartPaths(partPaths);
        downLoadBo.setBoundaryPaths(boundaryPaths);
        downLoadBo.setBoundaryExportPath(root);
        downLoadBo.setLoadPaths(loadPaths);
        downLoadBo.setLoadExportPath(root);
        downLoadBo.setNonstandardPaths(nonstandardocsPaths);
        downLoadBo.setNonstandardExportPath(root);
        downLoadBo.setNecessaryItemsList(necessaryItemsList);
        downLoadBo.setBatchNumber(batchNumber);
        // 2. 生成zip包，将索引文件 和 零件 根据指定目录放入到其中
        String zipFileName = id + ".zip";
        try (ServletOutputStream out = response.getOutputStream();
             ZipOutputStream zos = new ZipOutputStream(out)) {
            response.reset();
            response.setHeader("Content-Disposition", "attachment; filename=" + zipFileName);
            response.setContentType("application/zip");
            FileUtils.addPartAndIndexFileToZip(zos, downLoadBo, indexFileList);
            // 3. 完成ZIP输出流
            zos.finish();
        } catch (IOException e) {
            log.error("生成zip包失败", e);
            throw new BaseException("生成zip包失败，下载BDF失败");
        } finally {
            if (CollectionUtils.isNotEmpty(indexFileList)) {
                for (File file : indexFileList) {
                    if (file != null && file.exists()) {
                        file.delete();
                    }
                }
            }
        }
    }

    /**
     * 获取必备件挂在 到具体的部段 还是 组件下的索引地址
     */
    private String getNecessaryItemsIndexPaths(IsfdModelManagementNecessaryItemsVo isfdModelManagementNecessaryItemsVo) {
        String modelNumber = isfdModelManagementNecessaryItemsVo.getModelNumber();
        String batchNumber = isfdModelManagementNecessaryItemsVo.getBatchNumber();
        String sectionNumber = isfdModelManagementNecessaryItemsVo.getSectionNumber();
        String componentNumber = isfdModelManagementNecessaryItemsVo.getComponentNumber();
        String fileName = isfdModelManagementNecessaryItemsVo.getFileName();
        // 处理 挂载在批次下的必备件
        if (StringUtils.isNotBlank(modelNumber) && StringUtils.isNotBlank(batchNumber)
            && StringUtils.isBlank(sectionNumber) && StringUtils.isBlank(componentNumber)) {
            return modelNumber + "/" + fileName;
        }

        // 处理 挂载在部段下的必备件
        if (StringUtils.isNotBlank(modelNumber) && StringUtils.isNotBlank(batchNumber)
            && StringUtils.isNotBlank(sectionNumber) && StringUtils.isBlank(componentNumber)) {
            return modelNumber + "/" + sectionNumber + "/" + fileName;
        }

        // 处理 挂载在组件下的必备件
        if (StringUtils.isNotBlank(modelNumber) && StringUtils.isNotBlank(batchNumber)
            && StringUtils.isNotBlank(sectionNumber) && StringUtils.isNotBlank(componentNumber)) {
            return modelNumber + "/" + sectionNumber + "/" + componentNumber + "/" + fileName;
        }

        return modelNumber + "/" + fileName;
    }
}
